package nasp.labos.prvi.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

import nasp.labos.prvi.avltree.AVLTree;
import nasp.labos.prvi.avltree.Node;
import java.awt.Checkbox;
import javax.swing.JSeparator;

/**
 * Korisničko sučelje
 * @author Stjepan Hadjić
 *
 */
public class GUI {

	private JFrame frmAvlTree;
	private JTextField txtBrowse;
	private JTextField txtNumber;
	private AVLTree tree;
	private JButton btnBrowse = new JButton("Browse");
	private JButton btnLoad = new JButton("Load");
	private JButton btnGo = new JButton("Go");
	private JButton btnAdd = new JButton("Add");
	private JLabel lblInput = new JLabel("");
	private Checkbox checkbox = new Checkbox("step");
	private int i = 0;
	private final JPanel panelDraw = new DrawPanel();
	private List<Integer> list = new ArrayList<Integer>(); 

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					GUI window = new GUI();
					window.tree = new AVLTree();
					window.frmAvlTree.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public GUI() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmAvlTree = new JFrame();
		frmAvlTree.setTitle("AVL Tree");
		frmAvlTree.setBounds(100, 100, 1000, 500);
		frmAvlTree.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmAvlTree.getContentPane().setLayout(new BorderLayout(0, 0));
		
		JPanel panelTop = new JPanel();
		frmAvlTree.getContentPane().add(panelTop, BorderLayout.NORTH);
		panelTop.setLayout(new BoxLayout(panelTop, BoxLayout.PAGE_AXIS));
		
		JPanel panelBrowse = new JPanel();
		panelTop.add(panelBrowse);
		FlowLayout fl_panelBrowse = (FlowLayout) panelBrowse.getLayout();
		fl_panelBrowse.setAlignment(FlowLayout.LEFT);
		
		JLabel lblPath = new JLabel("Path:");
		panelBrowse.add(lblPath);
		
		txtBrowse = new JTextField();
		txtBrowse.setText("");
		panelBrowse.add(txtBrowse);
		txtBrowse.setColumns(25);
		txtBrowse.addActionListener(load());
		
		final JFileChooser fc = new JFileChooser("../nasp");
		btnBrowse.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e	) {
				 if (e.getSource() == btnBrowse) {
				        int returnVal = fc.showOpenDialog(frmAvlTree);
				        if (returnVal == JFileChooser.APPROVE_OPTION) {
				             txtBrowse.setText(fc.getSelectedFile().getAbsolutePath());
				        }
				 }
			}
		});
		panelBrowse.add(btnBrowse);
		
		
		btnLoad.addActionListener(load());
		panelBrowse.add(btnLoad);
		
		
		btnGo.addActionListener(go());
		btnGo.setEnabled(false);
		panelBrowse.add(btnGo);
		
		panelBrowse.add(checkbox);
		
		JSeparator separator = new JSeparator();
		panelBrowse.add(separator);
		
		JLabel lblNumber = new JLabel("Number:");
		panelBrowse.add(lblNumber);
		
		
		final JScrollPane scrollDraw = new JScrollPane(panelDraw);
		frmAvlTree.getContentPane().add(scrollDraw, BorderLayout.CENTER);
		
		txtNumber = new JTextField();
		txtNumber.addActionListener(add());
		panelBrowse.add(txtNumber);
		txtNumber.setHorizontalAlignment(SwingConstants.LEFT);
		txtNumber.setColumns(5);
		
		
		panelBrowse.add(btnAdd);
		
		JButton btnClear = new JButton("Clear");
		btnClear.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				tree.clear();
				list.clear();
				draw();
			}
		});
		panelBrowse.add(btnClear);
		
		JPanel panel = new JPanel();
		FlowLayout flowLayout = (FlowLayout) panel.getLayout();
		flowLayout.setAlignment(FlowLayout.LEFT);
		panelTop.add(panel);
		panel.add(lblInput);
		lblInput.setHorizontalAlignment(SwingConstants.LEFT);
		
		btnAdd.addActionListener(add());
	}
	
	/**
	 * Crta stablo
	 */
	public void draw(){
		panelDraw.setPreferredSize(new Dimension(tree.getMaxPoint().x, tree.getMaxPoint().y));
		panelDraw.repaint();
		frmAvlTree.setSize(frmAvlTree.getWidth()-1, frmAvlTree.getHeight()-1);
	}
	
	/**
	 * Dodaje element u AVL stablo te ga nacrta
	 * @return
	 */
	public ActionListener add(){
		return new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				tree.add(Integer.parseInt(txtNumber.getText()));
				draw();
				txtNumber.setText("");
				txtNumber.grabFocus();		
			}
		};
	}
	
	/**
	 * Cita iz txt datoteke ta tim redosljedom puni stablo. Na poslijetku nacrta to stablo.
	 * @return
	 */
	public ActionListener load(){
		return new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if(!txtBrowse.getText().endsWith(".txt")){
					JOptionPane.showMessageDialog(frmAvlTree, "Input file must be txt!");
					txtBrowse.selectAll();
					txtBrowse.grabFocus();
					return;
				}
				else{
					
					list.clear();
					tree.clear();
					BufferedReader reader = null;
					try{
						reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(txtBrowse.getText()))));	
					}catch (FileNotFoundException ex) {
						System.out.println("file "+txtBrowse.getText()+" not found!");
						return;
					}
					try {
						String line;
						String[] separatedLine;
						StringBuffer buffer = new StringBuffer("Input: ");
						while((line = reader.readLine())!=null){
							separatedLine = line.split(" ");
							for(String s : separatedLine){
								buffer.append(s);
								buffer.append(", ");
								list.add(Integer.valueOf(s));
							}
						}
						buffer.deleteCharAt(buffer.length()-2);
						lblInput.setText(buffer.toString());
						closeButtons(false);
					} catch (IOException ex) {
						System.out.println("file "+txtBrowse.getText()+" could not be read!");
						return;
					} finally { 
						try { reader.close(); } catch (IOException ignorable) {}}
				}
			}
		};
	}
	
	/**
	 * Zatvara gumbe Go, otvara gumbe add i text field Number
	 * @param close
	 */
	public void closeButtons(boolean close){
		btnGo.setEnabled(!close);
		btnAdd.setEnabled(close);
		txtNumber.setEnabled(close);
	}
	
	/**
	 * Dodaje elemente u stablo
	 * ovisno o checkboxu step,elementi se dodaju svi odjednom ili jedan po jedan 
	 * @return
	 */
	public ActionListener go(){
		return new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(!list.isEmpty()){
					if(checkbox.getState()) {
						tree.add(list.get(i));
						i++;
						if(i == list.size()){
							closeButtons(true);
						}
					}
					else{
						for(Integer i:list){
							tree.add(i);
						}
						closeButtons(true);
					}
					draw();
				}
			}
		};
	}
	
	/**
	 * Dio sučelja gdje se stablo crta
	 *
	 */
	class DrawPanel extends JPanel{
		
		private static final long serialVersionUID = 5620482285535096545L;
		public DrawPanel() {
			setBorder(BorderFactory.createLineBorder(Color.black));
			setBackground(Color.white);
		}
		
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			paintTree(tree.getRoot(), g);
		}
		
		public void paintTree(Node root,Graphics g){
			if(root == null)
				return;
			paintNode(root.point.x, root.point.y, root.element, root.balanceFactor,root.depth, g);
			if(root.parent != null)
				g.drawLine(root.point.x+25, root.point.y, root.parent.point.x+25, root.parent.point.y+50);
			paintTree(root.right, g);
			paintTree(root.left, g);
		}
		
		public void paintNode(int x, int y, int element, int BF,int depth, Graphics g){
			g.drawArc(x, y, 50, 50, 0, 360);
			g.drawString(""+element, x+20, y+30);
			g.drawString(""+BF, x+45,y+10);
		}
	}
}
